home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / bombs9.zip / COMBAT.QC < prev    next >
Text File  |  1996-10-15  |  9KB  |  394 lines

  1.  
  2. void() T_MissileTouch;
  3. void(entity inflictor, entity attacker, float damage, entity ignore) T_FlashDamage;
  4. void() info_player_start;
  5. void(entity targ, entity attacker, entity inflictor) ClientObituary;
  6.  
  7. void() monster_death_use;
  8.  
  9. //============================================================================
  10.  
  11. /*
  12. ============
  13. CanDamage
  14.  
  15. Returns true if the inflictor can directly damage the target.  Used for
  16. explosions and melee attacks.
  17. ============
  18. */
  19. float(entity targ, entity inflictor) CanDamage =
  20. {
  21. // bmodels need special checking because their origin is 0,0,0
  22.     if (targ.movetype == MOVETYPE_PUSH)
  23.     {
  24.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  25.         if (trace_fraction == 1)
  26.             return TRUE;
  27.         if (trace_ent == targ)
  28.             return TRUE;
  29.         return FALSE;
  30.     }
  31.     
  32.     traceline(inflictor.origin, targ.origin, TRUE, self);
  33.     if (trace_fraction == 1)
  34.         return TRUE;
  35.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  36.     if (trace_fraction == 1)
  37.         return TRUE;
  38.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  39.     if (trace_fraction == 1)
  40.         return TRUE;
  41.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  42.     if (trace_fraction == 1)
  43.         return TRUE;
  44.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  45.     if (trace_fraction == 1)
  46.         return TRUE;
  47.  
  48.     return FALSE;
  49. };
  50.  
  51.  
  52. /*
  53. ============
  54. Killed
  55. ============
  56. */
  57. void(entity targ, entity attacker, entity inflictor) Killed =
  58. {
  59.     local entity oself;
  60.  
  61.     oself = self;
  62.     self = targ;
  63.     
  64.     if (self.health < -99)
  65.         self.health = -99;        // don't let sbar look bad if a player
  66.  
  67.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  68.     {    // doors, triggers, etc
  69.         self.th_die ();
  70.         self = oself;
  71.         return;
  72.     }
  73.  
  74.     self.enemy = attacker;
  75.  
  76. // bump the monster counter
  77.     if (self.flags & FL_MONSTER)
  78.     {
  79.         killed_monsters = killed_monsters + 1;
  80.         WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  81.     }
  82.  
  83.     ClientObituary(self, attacker, inflictor);
  84.     
  85.     self.takedamage = DAMAGE_NO;
  86.     self.touch = SUB_Null;
  87.  
  88.     monster_death_use();
  89.     self.th_die ();
  90.     
  91.     self = oself;
  92. };
  93.  
  94.  
  95. /*
  96. ============
  97. T_Damage
  98.  
  99. The damage is coming from inflictor, but get mad at attacker
  100. This should be the only function that ever reduces health.
  101. ============
  102. */
  103. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  104. {
  105.     local    vector    dir;
  106.     local    entity    oldself;
  107.     local    float    save;
  108.     local    float    take;
  109.  
  110.     if (!targ.takedamage)
  111.         return;
  112.  
  113. // used by buttons and triggers to set activator for target firing
  114.     damage_attacker = attacker;
  115.  
  116. // check for quad damage powerup on the attacker
  117.     if (attacker.super_damage_finished > time)
  118.         damage = damage * 4;
  119.  
  120. // save damage based on the target's armor level
  121.  
  122.     save = ceil(targ.armortype*damage);
  123.     if (save >= targ.armorvalue)
  124.     {
  125.         save = targ.armorvalue;
  126.         targ.armortype = 0;    // lost all armor
  127.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  128.     }
  129.     
  130.     targ.armorvalue = targ.armorvalue - save;
  131.     take = ceil(damage-save);
  132.  
  133. // add to the damage total for clients, which will be sent as a single
  134. // message at the end of the frame
  135. // FIXME: remove after combining shotgun blasts?
  136.     if (targ.flags & FL_CLIENT)
  137.     {
  138.         targ.dmg_take = targ.dmg_take + take;
  139.         targ.dmg_save = targ.dmg_save + save;
  140.         targ.dmg_inflictor = inflictor;
  141.     }
  142.  
  143. // figure momentum add
  144.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  145.     {
  146.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  147.         dir = normalize(dir);
  148.         targ.velocity = targ.velocity + dir*damage*8;
  149.     }
  150.  
  151. // check for godmode or invincibility
  152.     if (targ.flags & FL_GODMODE)
  153.         return;
  154.     if (targ.invincible_finished >= time)
  155.     {
  156.         if (self.invincible_sound < time)
  157.         {
  158.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  159.             self.invincible_sound = time + 2;
  160.         }
  161.         return;
  162.     }
  163.  
  164. // team play damage avoidance
  165.     if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  166.         return;
  167.         
  168. // do the damage
  169.     targ.health = targ.health - take;
  170.             
  171.     if (targ.health <= 0)
  172.     {
  173.         Killed (targ, attacker, inflictor);
  174.         return;
  175.     }
  176.  
  177. // react to the damage
  178.     oldself = self;
  179.     self = targ;
  180.  
  181.     if ( (self.flags & FL_MONSTER) && attacker != world)
  182.     {
  183.     // get mad unless of the same class (except for soldiers)
  184.         if (self != attacker && attacker != self.enemy)
  185.         {
  186.             if ( (self.classname != attacker.classname) 
  187.             || (self.classname == "monster_army" ) )
  188.             {
  189.                 if (self.enemy.classname == "player")
  190.                     self.oldenemy = self.enemy;
  191.                 self.enemy = attacker;
  192.                 FoundTarget ();
  193.             }
  194.         }
  195.     }
  196.  
  197.     if (self.th_pain)
  198.     {
  199.         self.th_pain (attacker, take);
  200.     // nightmare mode monsters don't go into pain frames often
  201.         if (skill == 3)
  202.             self.pain_finished = time + 5;        
  203.     }
  204.  
  205.     self = oldself;
  206. };
  207.  
  208. /*
  209. ============
  210. T_RadiusDamage
  211. ============
  212. */
  213. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  214. {
  215.     local    float     points;
  216.     local    entity    head;
  217.     local    vector    org;
  218.  
  219.     head = findradius(inflictor.origin, damage+40);
  220.     
  221.     while (head)
  222.     {
  223.         if (head != ignore)
  224.         {
  225.             if (head.takedamage)
  226.             {
  227.                 org = head.origin + (head.mins + head.maxs)*0.5;
  228.                 points = 0.5*vlen (inflictor.origin - org);
  229.                 if (points < 0)
  230.                     points = 0;
  231.                 points = damage - points;
  232.                 if (head == attacker)
  233.                     points = points * 0.5;
  234.                 if (points > 0)
  235.                 {
  236.                     if (CanDamage (head, inflictor))
  237.                     {    // shambler takes half damage from all explosions
  238.                         if (head.classname == "monster_shambler")                        
  239.                             T_Damage (head, inflictor, attacker, points*0.5);
  240.                         else
  241.                             T_Damage (head, inflictor, attacker, points);
  242.                     }
  243.                 }
  244.             }
  245.         }
  246.         head = head.chain;
  247.     }
  248. };
  249.  
  250. void() flashSpawn;
  251. void() flashSpawn = 
  252. {
  253.         local string    brightn;
  254.         local entity flash_owner;
  255.  
  256.         stuffcmd(self.owner, "gamma ");
  257.         brightn = ftos(0.5 - self.bubble_count*0.04);
  258.         stuffcmd(self.owner, brightn);
  259.         stuffcmd(self.owner, "\n");
  260.  
  261.     if (self.bubble_count < 0) 
  262.         {
  263.             flash_owner = self.owner;
  264.             flash_owner.lefty = 0;
  265.             stuffcmd(self.owner, "gamma 0.6\n");
  266.             remove(self);
  267.             return;
  268.         }
  269.  
  270.     self.bubble_count = self.bubble_count - 1;
  271.     self.nextthink = time + 0.4;
  272.     self.think = flashSpawn;
  273.  
  274. };
  275.  
  276. /*
  277. ============
  278. T_FlashDamage
  279. ============
  280. */
  281. void(entity inflictor, entity attacker, float damage, entity ignore) T_FlashDamage =
  282. {
  283.     local    float     points;
  284.     local    entity    head;
  285.     local    vector    org;
  286.  
  287.     head = findradius(inflictor.origin, damage+40);
  288.     
  289.     while (head)
  290.     {
  291.         if ((head != ignore) && (head.classname == "player"))
  292.         {
  293.             if (head.takedamage)
  294.             {
  295.                 org = head.origin + (head.mins + head.maxs)*0.5;
  296.                 points = 0.5*vlen (inflictor.origin - org);
  297.                 if (points < 0)
  298.                     points = 0;
  299.                 points = damage - points;
  300.                 if (head == attacker)
  301.                 points = points * 0.6;
  302.                 if (points > 0)
  303.                 {
  304.                     if (CanDamage (head, inflictor))
  305.                     {    
  306.  
  307.                         local vector org1,org2;
  308.                         local float flashdist;
  309.  
  310.                         makevectors(head.v_angle);
  311.                         org1 = normalize(v_forward);
  312.                         org2 = normalize(inflictor.origin - org);
  313.                         flashdist = vlen(org1 - org2);
  314.                         if ( flashdist < 0.9)
  315.                             {
  316.                             local entity    flash_spawner;
  317.                             local string    brightn;
  318.                             sound (head, CHAN_VOICE, "player/pain4.wav", 1, ATTN_NORM);
  319.                                 if ( head.lefty == 123456789 )
  320.                                     {
  321.                                     flash_spawner = head.movetarget;
  322.                                     if ( flash_spawner.bubble_count > points*0.02)
  323.                                         {
  324.                                         points = flash_spawner.bubble_count * 50;
  325.                                         }
  326.                                     } else {    
  327.                                         flash_spawner = spawn();
  328.                                         setorigin (flash_spawner, head.origin);
  329.                                         flash_spawner.movetype = MOVETYPE_NONE;
  330.                                         flash_spawner.solid = SOLID_NOT;
  331.                                         flash_spawner.owner = head;
  332.                                         head.lefty = 123456789;
  333.                                         head.movetarget = flash_spawner;
  334.                                         }    
  335.                             
  336.  
  337.                             flash_spawner.nextthink = time + 0.4;
  338.                             flash_spawner.think = flashSpawn;
  339.                             flash_spawner.bubble_count = points*0.02;
  340.         stuffcmd(head, "gamma ");
  341.         brightn = ftos(0.5 - flash_spawner.bubble_count*0.04);
  342.         stuffcmd(head, brightn);
  343.         stuffcmd(head, "\n");
  344.  
  345.  
  346.  
  347. }
  348.  
  349.                     }
  350.                 }
  351.             }
  352.         }
  353.         head = head.chain;
  354.     }
  355. };
  356.  
  357. /*
  358. ============
  359. T_BeamDamage
  360. ============
  361. */
  362. void(entity attacker, float damage) T_BeamDamage =
  363. {
  364.     local    float     points;
  365.     local    entity    head;
  366.     
  367.     head = findradius(attacker.origin, damage+40);
  368.     
  369.     while (head)
  370.     {
  371.         if (head.takedamage)
  372.         {
  373.             points = 0.5*vlen (attacker.origin - head.origin);
  374.             if (points < 0)
  375.                 points = 0;
  376.             points = damage - points;
  377.             if (head == attacker)
  378.                 points = points * 0.5;
  379.             if (points > 0)
  380.             {
  381.                 if (CanDamage (head, attacker))
  382.                 {
  383.                     if (head.classname == "monster_shambler")                        
  384.                         T_Damage (head, attacker, attacker, points*0.5);
  385.                     else
  386.                         T_Damage (head, attacker, attacker, points);
  387.                 }
  388.             }
  389.         }
  390.         head = head.chain;
  391.     }
  392. };
  393.  
  394.